/*
 * $Id: AlbumAndSongList.java 358 2008-04-14 18:20:23Z jasta $
 *
 * Copyright (C) 2008 Josh Guilfoyle <jasta@devtcg.org>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

package org.devtcg.five.music.activity;

import org.devtcg.five.music.R;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

public class AlbumAndSongList extends PlayNotifActivity
{
	private static final String TAG = "AlbumAndSongList";

	private static final String PROJECTION_ARTIST[] = {
		"_id", "full_name", "photo"
	};

	private static final String PROJECTION_ALBUMS[] = {
		"_id", "name", "full_name", "artwork"
	};

	private static final String PROJECTION_SONGS[] = {
		"_id", "title", "length", "track_num"
	};

	private Cursor mCursorArtist;
	private Cursor mCursorAlbums;
	private Cursor mCursorSongs;

    @Override
    public void onCreate(Bundle icicle)
    {
        super.onCreate(icicle);
    	requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.album_and_song_list);

        Uri artist = getIntent().getData();

        if (artist == null)
        	throw new IllegalArgumentException("No artist given, cannot do thy bidding");

        mCursorArtist = managedQuery(artist, PROJECTION_ARTIST, null, null, null);
        setArtistText();

        mCursorArtist.registerContentObserver(new ContentObserver(new Handler()) {
        	public void onChange(boolean selfChange)
        	{
        		assert selfChange == false : "Is someone using our cursor other than us?";
        		setArtistText();
        	}
        });

        Uri albums = artist.buildUpon()
          .appendPath("albums")
          .build();

        Uri songs = artist.buildUpon()
          .appendPath("songs")
          .build();

        mCursorAlbums = managedQuery(albums, PROJECTION_ALBUMS, null, null, "a.name ASC");
        mCursorSongs = managedQuery(songs, PROJECTION_SONGS, "album_id IS NULL", null, "title ASC");
        
        /* Convenience for when there is only one album by this artist. */
        if (mCursorAlbums.count() == 1 && mCursorSongs.count() == 0)
        	chooseOnlyAlbum();

        ListView list = (ListView)findViewById(android.R.id.list);

        ListAdapter adapter =
          new AlbumAndSongAdapter(this, mCursorAlbums, mCursorSongs);
        
        list.setOnItemClickListener(mOnItemClickListener);

        list.setAdapter(adapter);
    }

    /**
     * Set the artist text based on the underlying cursor.  This function has
     * a side-effect that the activity will be dismissed if the cursor is empty.
     */
    private void setArtistText()
    {
    	if (mCursorArtist.count() == 0)
    		finish();

        mCursorArtist.first();

        ((TextView)findViewById(R.id.artist_name)).setText(mCursorArtist.getString(1));

//        String photo = mCursorArtist.getString(2);
//        ImageView photoView = (ImageView)findViewById(R.id.artist_photo);
//
//        if (photo != null)
//        	photoView.setImageURI(Uri.parse(photo));
//        else
//        	photoView.setVisibility(View.GONE);   	
    }
    
    private void chooseOnlyAlbum()
    {
        mCursorAlbums.first();
        long albumId = mCursorAlbums.getLong(0);
        
        Uri chosen = Uri.parse("content://org.devtcg.five/media/music/albums").buildUpon()
		  .appendPath(String.valueOf(albumId))
		  .build();

		startActivity(new Intent(Intent.VIEW_ACTION, chosen));
		finish();
    }

    private OnItemClickListener mOnItemClickListener = new OnItemClickListener()
    {
		public void onItemClick(AdapterView av, View v, int pos, long id)
		{
			Intent i = getIntent();

			Uri chosen;

			/* TODO: Currently we only support clicking on an album. */
			if ((Integer)v.getTag() == AlbumAndSongAdapter.ITEM_TYPE_SONG)
			{
				chosen = Uri.parse("content://org.devtcg.five/media/music/songs").buildUpon()
				  .appendPath(String.valueOf(id))
				  .build();
			}
			else
			{
				chosen = Uri.parse("content://org.devtcg.five/media/music/albums").buildUpon()
				  .appendPath(String.valueOf(id))
				  .build();
			}

			String action = i.getAction();

			Log.d(TAG, "uri=" + chosen.toString());
			Log.d(TAG, "action=" + action);

			if (action.equals(Intent.PICK_ACTION) == true ||
			    action.equals(Intent.GET_CONTENT_ACTION) == true)
			{
				setResult(RESULT_OK, chosen.toString());
				finish();
			}
			else
			{
				startActivity(new Intent(Intent.VIEW_ACTION, chosen));
			}
		}
    };

    /**
     * Custom adapter that "intelligently" joins albums and song tracks into a
     * ListView.  The logic is based on the variability and depth of the
     * collection found, offering features like sorted albums by full-length
     * vs EP/demo, listing songs directly when only a small number of tracks 
     * are present, etc.
     */
    private static class AlbumAndSongAdapter extends BaseAdapter
    {
    	private Context mContext;
    	private Cursor mAlbums;
    	private Cursor mSongs;
    	private boolean mAlbumsOK;
    	private boolean mSongsOK;

    	private SimpleCursorAdapter mAlbumsAd;
    	private SimpleCursorAdapter mSongsAd;

    	private boolean mExpandAlbums;
    	
    	public static final int ITEM_TYPE_ALBUM = 0;
    	public static final int ITEM_TYPE_SONG = 1;

    	public AlbumAndSongAdapter(Context ctx, Cursor c_album, Cursor c_song)
    	{
    		mContext = ctx;

    		mAlbumsOK = true;
    		mSongsOK = true;
    		mAlbums = c_album;
    		mSongs = c_song;

    		mAlbumsAd = new SimpleCursorAdapter(ctx,
    		  R.layout.artist_album_list_item, c_album,
    		  new String[] { "artwork", "full_name" },
    		  new int[] { R.id.album_cover, R.id.album_name });
    		
    		mAlbumsAd.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
    			public boolean setViewValue(View v, Cursor c, int col)
    			{
    				if (col != c.getColumnIndex("artwork"))
    					return false;

    				ImageView iv = (ImageView)v;

    				if (c.isNull(col) == true)
    					iv.setImageResource(R.drawable.lastfm_cover_small);
    				else
    					iv.setImageURI(Uri.parse(c.getString(col)));

    				return true;
    			}
    		});
    		
    		mSongsAd = new SimpleCursorAdapter(ctx,
    		  R.layout.song_list_item, c_song,
    		  new String[] { "track_num", "title", "length" },
    		  new int[] { R.id.song_track, R.id.song_name, R.id.song_length });

    		mSongsAd.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
    			public boolean setViewValue(View v, Cursor c, int col)
    			{
    				if (col != c.getColumnIndex("length"))
    					return false;

    				int seconds = c.getInt(col);
    				int minutes = seconds / 60;
    				seconds = seconds % 60;
    				
    				StringBuilder b = new StringBuilder();
    				b.append(minutes);
    				b.append(':');
    				
    				if (seconds < 10)
    					b.append('0');
    				
    				b.append(seconds);
    				
    				((TextView)v).setText(b.toString());
    				
    				return true;
    			}
    		});
    		
    		c_album.registerDataSetObserver(new DataSetObserver() {
    			public void onChanged()
    			{
    				mAlbumsOK = true;
    				notifyDataSetChanged();
    			}
    			
    			public void onInvalidated()
    			{
    				mAlbumsOK = false;
    				notifyDataSetInvalidated();
    			}
    		});

    		c_song.registerDataSetObserver(new DataSetObserver() {
    			public void onChanged()
    			{
    				mSongsOK = true;
    				notifyDataSetChanged();
    			}
    			
    			public void onInvalidated()
    			{
    				mSongsOK = false;
    				notifyDataSetInvalidated();
    			}
    		});
    		
    		determineLayout();
    	}
    	
    	protected final boolean areCursorsValid()
    	{
    		if (mSongsOK == false || mAlbumsOK == false)
    			return false;
    		
    		return true;
    	}

    	protected void determineLayout()
    	{
    		mExpandAlbums = false;
    		
    		if (areCursorsValid() == false)
    			return;
    		
//    		if (mAlbums.count() <= 2)
//    			mExpandAlbums = true;
    	}

		public int getCount() 
		{
			if (areCursorsValid() == false)
				return 0;

			assert mExpandAlbums == false : "TODO";

			return mAlbumsAd.getCount() + mSongsAd.getCount();
		}

		public Object getItem(int position)
		{
			if (areCursorsValid() == false)
				return null;
			
			assert mExpandAlbums == false : "TODO";
			
			int nalbums = mAlbums.count();
			
			if (position < nalbums)
				return mAlbumsAd.getItem(position);
			
			return mSongsAd.getItem(position - nalbums);
		}

		public long getItemId(int position) 
		{
			if (areCursorsValid() == false)
				return -1;

			assert mExpandAlbums == false : "TODO";

			int nalbums = mAlbums.count();

			if (position < nalbums)
				return mAlbumsAd.getItemId(position);

			return mSongsAd.getItemId(position - nalbums);
		}

		public View getView(int position, View convert, ViewGroup parent)
		{
			if (areCursorsValid() == false)
				throw new IllegalStateException("this should only be called when the cursors are valid");
			
			assert mExpandAlbums == false : "TODO";
			
			int nalbums = mAlbums.count();
			
			View v;
			
			if (position < nalbums)
			{
				if (convert != null && (Integer)convert.getTag() != ITEM_TYPE_ALBUM)
					convert = null;
				
				v = mAlbumsAd.getView(position, null, parent);
				v.setTag(ITEM_TYPE_ALBUM);
			}
			else
			{
				if (convert != null && (Integer)convert.getTag() != ITEM_TYPE_SONG)
					convert = null;
				
				v = mSongsAd.getView(position - nalbums, null, parent);
				v.setTag(ITEM_TYPE_SONG);
			}
			
			return v;
		}
    }
}
